home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gxcmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  30.0 KB  |  947 lines

  1. /* Copyright (C) 1992, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gxcmap.c,v 1.3 2000/09/19 19:00:35 lpd Exp $ */
  20. /* Color mapping for Ghostscript */
  21. #include "gx.h"
  22. #include "gserrors.h"
  23. #include "gsccolor.h"
  24. #include "gxalpha.h"
  25. #include "gxcspace.h"
  26. #include "gxfarith.h"
  27. #include "gxfrac.h"
  28. #include "gxdcconv.h"
  29. #include "gxdevice.h"
  30. #include "gxcmap.h"
  31. #include "gxlum.h"
  32. #include "gzstate.h"
  33. #include "gxdither.h"
  34.  
  35. /* Structure descriptor */
  36. public_st_device_color();
  37. private 
  38. ENUM_PTRS_WITH(device_color_enum_ptrs, gx_device_color *cptr)
  39. {
  40.     return ENUM_USING(*cptr->type->stype, vptr, size, index);
  41. }
  42. ENUM_PTRS_END
  43. private RELOC_PTRS_WITH(device_color_reloc_ptrs, gx_device_color *cptr)
  44. {
  45.     RELOC_USING(*cptr->type->stype, vptr, size);
  46. }
  47. RELOC_PTRS_END
  48.  
  49. /* ------ Trace device mapping procedures ------ */
  50.  
  51. /* If DEBUG is defined, these procedures substitute for direct calls */
  52. /* on the device map_{rgb,cmyk}_color procedures. */
  53.  
  54. gx_color_index
  55. gx_proc_map_rgb_color(gx_device * dev,
  56.             gx_color_value vr, gx_color_value vg, gx_color_value vb)
  57. {
  58.     gx_color_index cindex =
  59.     (*dev_proc(dev, map_rgb_color)) (dev, vr, vg, vb);
  60.  
  61.     if_debug5('C', "%s [C]RGB %u,%u,%u -> color 0x%lx\n",
  62.           dev->dname, (uint) vr, (uint) vg, (uint) vb, (ulong) cindex);
  63.     return cindex;
  64. }
  65.  
  66. gx_color_index
  67. gx_proc_map_rgb_alpha_color(gx_device * dev,
  68.  gx_color_value vr, gx_color_value vg, gx_color_value vb, gx_color_value va)
  69. {
  70.     gx_color_index cindex =
  71.     (*dev_proc(dev, map_rgb_alpha_color)) (dev, vr, vg, vb, va);
  72.  
  73.     if_debug6('C', "[C]%s RGBA %u,%u,%u,%u -> color 0x%lx\n",
  74.           dev->dname, (uint) vr, (uint) vg, (uint) vb, (uint) va,
  75.           (ulong) cindex);
  76.     return cindex;
  77. }
  78.  
  79. gx_color_index
  80. gx_proc_map_cmyk_color(gx_device * dev,
  81.  gx_color_value vc, gx_color_value vm, gx_color_value vy, gx_color_value vk)
  82. {
  83.     gx_color_index cindex =
  84.     (*dev_proc(dev, map_cmyk_color)) (dev, vc, vm, vy, vk);
  85.  
  86.     if_debug6('C', "[C]%s CMYK %u,%u,%u,%u -> color 0x%lx\n",
  87.           dev->dname, (uint) vc, (uint) vm, (uint) vy, (uint) vk,
  88.           (ulong) cindex);
  89.     return cindex;
  90. }
  91.  
  92. /* ---------------- Device color rendering ---------------- */
  93.  
  94. private cmap_proc_gray(cmap_gray_halftoned);
  95. private cmap_proc_gray(cmap_gray_direct);
  96. private cmap_proc_gray(cmap_gray_to_rgb_halftoned);
  97. private cmap_proc_gray(cmap_gray_to_rgb_direct);
  98. private cmap_proc_gray(cmap_gray_to_cmyk_halftoned);
  99. private cmap_proc_gray(cmap_gray_to_cmyk_direct);
  100. private cmap_proc_rgb(cmap_rgb_halftoned);
  101. private cmap_proc_rgb(cmap_rgb_direct);
  102. private cmap_proc_rgb(cmap_rgb_to_gray_halftoned);
  103. private cmap_proc_rgb(cmap_rgb_to_gray_direct);
  104. private cmap_proc_rgb(cmap_rgb_to_cmyk);
  105.  
  106. #define cmap_cmyk_halftoned cmap_cmyk_direct
  107. private cmap_proc_cmyk(cmap_cmyk_direct);
  108. private cmap_proc_cmyk(cmap_cmyk_to_gray);
  109. private cmap_proc_cmyk(cmap_cmyk_to_rgb);
  110. private cmap_proc_rgb_alpha(cmap_rgb_alpha_halftoned);
  111. private cmap_proc_rgb_alpha(cmap_rgb_alpha_direct);
  112.  
  113. /* Procedure names are only guaranteed unique to 23 characters.... */
  114. private cmap_proc_rgb_alpha(cmap_rgb_alpha2gray_halftoned);
  115. private cmap_proc_rgb_alpha(cmap_rgb_alpha2gray_direct);
  116. private cmap_proc_rgb_alpha(cmap_rgb_alpha_to_cmyk);
  117.  
  118. private const gx_color_map_procs
  119.       cmap_gray_few =
  120. {cmap_gray_halftoned, cmap_rgb_to_gray_halftoned, cmap_cmyk_to_gray,
  121.  cmap_rgb_alpha2gray_halftoned
  122. },    cmap_gray_many =
  123. {cmap_gray_direct, cmap_rgb_to_gray_direct, cmap_cmyk_to_gray,
  124.  cmap_rgb_alpha2gray_direct
  125. },    cmap_rgb_few =
  126. {cmap_gray_to_rgb_halftoned, cmap_rgb_halftoned, cmap_cmyk_to_rgb,
  127.  cmap_rgb_alpha_halftoned
  128. },    cmap_rgb_many =
  129. {cmap_gray_to_rgb_direct, cmap_rgb_direct, cmap_cmyk_to_rgb,
  130.  cmap_rgb_alpha_direct
  131. },    cmap_cmyk_few =
  132. {cmap_gray_to_cmyk_halftoned, cmap_rgb_to_cmyk, cmap_cmyk_halftoned,
  133.  cmap_rgb_alpha_to_cmyk
  134. },    cmap_cmyk_many =
  135. {cmap_gray_to_cmyk_direct, cmap_rgb_to_cmyk, cmap_cmyk_direct,
  136.  cmap_rgb_alpha_to_cmyk
  137. };
  138.  
  139. const gx_color_map_procs *const cmap_procs_default = &cmap_gray_many;
  140.  
  141. private const gx_color_map_procs *const cmap_few[] =
  142. {
  143.     0, &cmap_gray_few, 0, &cmap_rgb_few, &cmap_cmyk_few
  144. };
  145.  
  146. private const gx_color_map_procs *const cmap_many[] =
  147. {
  148.     0, &cmap_gray_many, 0, &cmap_rgb_many, &cmap_cmyk_many
  149. };
  150.  
  151. /* Determine the color mapping procedures for a device. */
  152. /* Note that the default procedure doesn't consult the imager state. */
  153. const gx_color_map_procs *
  154. gx_get_cmap_procs(const gs_imager_state *pis, const gx_device * dev)
  155. {
  156.     return (pis->get_cmap_procs)(pis, dev);
  157. }
  158. const gx_color_map_procs *
  159. gx_default_get_cmap_procs(const gs_imager_state *pis, const gx_device * dev)
  160. {
  161.     return (gx_device_must_halftone(dev) ? cmap_few : cmap_many)
  162.     [dev->color_info.num_components];
  163. }
  164.  
  165. /* Set the color mapping procedures in the graphics state. */
  166. void
  167. gx_set_cmap_procs(gs_imager_state * pis, const gx_device * dev)
  168. {
  169.     pis->cmap_procs = gx_get_cmap_procs(pis, dev);
  170. }
  171.  
  172. /* Remap the color in the graphics state. */
  173. int
  174. gx_remap_color(gs_state * pgs)
  175. {
  176.     const gs_color_space *pcs = pgs->color_space;
  177.  
  178.     /* The current color in the graphics state is always used for */
  179.     /* the texture, never for the source. */
  180.     return (*pcs->type->remap_color) (pgs->ccolor, pcs, pgs->dev_color,
  181.                       (gs_imager_state *) pgs, pgs->device,
  182.                       gs_color_select_texture);
  183. }
  184.  
  185. /* Indicate that a color space has no underlying concrete space. */
  186. const gs_color_space *
  187. gx_no_concrete_space(const gs_color_space * pcs, const gs_imager_state * pis)
  188. {
  189.     return NULL;
  190. }
  191.  
  192. /* Indicate that a color space is concrete. */
  193. const gs_color_space *
  194. gx_same_concrete_space(const gs_color_space * pcs, const gs_imager_state * pis)
  195. {
  196.     return pcs;
  197. }
  198.  
  199. /* Indicate that a color cannot be concretized. */
  200. int
  201. gx_no_concretize_color(const gs_client_color * pcc, const gs_color_space * pcs,
  202.                frac * pconc, const gs_imager_state * pis)
  203. {
  204.     return_error(gs_error_rangecheck);
  205. }
  206.  
  207. /* By default, remap a color by concretizing it and then */
  208. /* remapping the concrete color. */
  209. int
  210. gx_default_remap_color(const gs_client_color * pcc, const gs_color_space * pcs,
  211.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  212.                gs_color_select_t select)
  213. {
  214.     frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
  215.     const gs_color_space *pconcs;
  216.     int code = (*pcs->type->concretize_color)(pcc, pcs, conc, pis);
  217.  
  218.     if (code < 0)
  219.     return code;
  220.     pconcs = cs_concrete_space(pcs, pis);
  221.     return (*pconcs->type->remap_concrete_color)(conc, pdc, pis, dev, select);
  222. }
  223.  
  224. /* Color remappers for the standard color spaces. */
  225. /* Note that we use D... instead of Device... in some places because */
  226. /* gcc under VMS only retains 23 characters of procedure names. */
  227.  
  228. #define unit_frac(v, ftemp)\
  229.   (ftemp = (v),\
  230.    (is_fneg(ftemp) ? frac_0 : is_fge1(ftemp) ? frac_1 : float2frac(ftemp)))
  231.  
  232. /* DeviceGray */
  233. int
  234. gx_concretize_DeviceGray(const gs_client_color * pc, const gs_color_space * pcs,
  235.              frac * pconc, const gs_imager_state * pis)
  236. {
  237.     float ftemp;
  238.  
  239.     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
  240.     return 0;
  241. }
  242. int
  243. gx_remap_concrete_DGray(const frac * pconc,
  244.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  245.             gs_color_select_t select)
  246. {
  247.     if (pis->alpha == gx_max_color_value)
  248.     (*pis->cmap_procs->map_gray)
  249.         (pconc[0], pdc, pis, dev, select);
  250.     else
  251.     (*pis->cmap_procs->map_rgb_alpha)
  252.         (pconc[0], pconc[0], pconc[0], cv2frac(pis->alpha),
  253.          pdc, pis, dev, select);
  254.     return 0;
  255. }
  256. int
  257. gx_remap_DeviceGray(const gs_client_color * pc, const gs_color_space * pcs,
  258.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  259.             gs_color_select_t select)
  260. {
  261.     float ftemp;
  262.     frac fgray = unit_frac(pc->paint.values[0], ftemp);
  263.  
  264.     if (pis->alpha == gx_max_color_value)
  265.     (*pis->cmap_procs->map_gray)
  266.         (fgray, pdc, pis, dev, select);
  267.     else
  268.     (*pis->cmap_procs->map_rgb_alpha)
  269.         (fgray, fgray, fgray, cv2frac(pis->alpha), pdc, pis, dev, select);
  270.     return 0;
  271. }
  272.  
  273. /* DeviceRGB */
  274. int
  275. gx_concretize_DeviceRGB(const gs_client_color * pc, const gs_color_space * pcs,
  276.             frac * pconc, const gs_imager_state * pis)
  277. {
  278.     float ftemp;
  279.  
  280.     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
  281.     pconc[1] = unit_frac(pc->paint.values[1], ftemp);
  282.     pconc[2] = unit_frac(pc->paint.values[2], ftemp);
  283.     return 0;
  284. }
  285. int
  286. gx_remap_concrete_DRGB(const frac * pconc,
  287.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  288.                gs_color_select_t select)
  289. {
  290.     if (pis->alpha == gx_max_color_value)
  291.     gx_remap_concrete_rgb(pconc[0], pconc[1], pconc[2],
  292.                   pdc, pis, dev, select);
  293.     else
  294.     gx_remap_concrete_rgb_alpha(pconc[0], pconc[1], pconc[2],
  295.                     cv2frac(pis->alpha),
  296.                     pdc, pis, dev, select);
  297.     return 0;
  298. }
  299. int
  300. gx_remap_DeviceRGB(const gs_client_color * pc, const gs_color_space * pcs,
  301.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  302.            gs_color_select_t select)
  303. {
  304.     float ftemp;
  305.     frac fred = unit_frac(pc->paint.values[0], ftemp), fgreen = unit_frac(pc->paint.values[1], ftemp),
  306.          fblue = unit_frac(pc->paint.values[2], ftemp);
  307.  
  308.     if (pis->alpha == gx_max_color_value)
  309.     gx_remap_concrete_rgb(fred, fgreen, fblue,
  310.                   pdc, pis, dev, select);
  311.     else
  312.     gx_remap_concrete_rgb_alpha(fred, fgreen, fblue, cv2frac(pis->alpha),
  313.                     pdc, pis, dev, select);
  314.     return 0;
  315. }
  316.  
  317. /* DeviceCMYK */
  318. int
  319. gx_concretize_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs,
  320.              frac * pconc, const gs_imager_state * pis)
  321. {
  322.     float ftemp;
  323.  
  324.     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
  325.     pconc[1] = unit_frac(pc->paint.values[1], ftemp);
  326.     pconc[2] = unit_frac(pc->paint.values[2], ftemp);
  327.     pconc[3] = unit_frac(pc->paint.values[3], ftemp);
  328.     return 0;
  329. }
  330. int
  331. gx_remap_concrete_DCMYK(const frac * pconc,
  332.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  333.             gs_color_select_t select)
  334. {
  335. /****** IGNORE alpha ******/
  336.     gx_remap_concrete_cmyk(pconc[0], pconc[1], pconc[2], pconc[3], pdc,
  337.                pis, dev, select);
  338.     return 0;
  339. }
  340. int
  341. gx_remap_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs,
  342.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  343.             gs_color_select_t select)
  344. {
  345. /****** IGNORE alpha ******/
  346.     float ft0, ft1, ft2, ft3;
  347.  
  348.     gx_remap_concrete_cmyk(unit_frac(pc->paint.values[0], ft0),
  349.                unit_frac(pc->paint.values[1], ft1),
  350.                unit_frac(pc->paint.values[2], ft2),
  351.                unit_frac(pc->paint.values[3], ft3),
  352.                pdc, pis, dev, select);
  353.     return 0;
  354. }
  355.  
  356. /* ------ Render Gray color. ------ */
  357.  
  358. private void
  359. cmap_gray_halftoned(frac gray, gx_device_color * pdc,
  360.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  361. {
  362.     if (gx_render_gray(gx_map_color_frac(pis, gray, effective_transfer.colored.gray), pdc, pis, dev, select) == 1)
  363.     gx_color_load_select(pdc, pis, dev, select);
  364. }
  365.  
  366. private void
  367. cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_imager_state * pis,
  368.          gx_device * dev, gs_color_select_t select)
  369. {
  370.     frac mgray = gx_map_color_frac(pis, gray, effective_transfer.colored.gray);
  371.     gx_color_value cv_gray = frac2cv(mgray);
  372.     gx_color_index color =
  373.     (pis->alpha == gx_max_color_value ?
  374.      gx_map_rgb_color(dev, cv_gray, cv_gray, cv_gray) :
  375.      gx_map_rgb_alpha_color(dev, cv_gray, cv_gray, cv_gray, pis->alpha));
  376.  
  377.     if (color == gx_no_color_index) {
  378.     if (gx_render_gray(mgray, pdc, pis, dev, select) == 1)
  379.         gx_color_load_select(pdc, pis, dev, select);
  380.     return;
  381.     }
  382.     color_set_pure(pdc, color);
  383. }
  384.  
  385. private void
  386. cmap_gray_to_rgb_halftoned(frac gray, gx_device_color * pdc,
  387.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  388. {
  389.     cmap_rgb_halftoned(gray, gray, gray, pdc, pis, dev, select);
  390. }
  391.  
  392. private void
  393. cmap_gray_to_rgb_direct(frac gray, gx_device_color * pdc,
  394.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  395. {
  396.     cmap_rgb_direct(gray, gray, gray, pdc, pis, dev, select);
  397. }
  398.  
  399. private void
  400. cmap_gray_to_cmyk_halftoned(frac gray, gx_device_color * pdc,
  401.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  402. {                /*
  403.                  * Per the last paragraph of section 6.3 (p. 309) of the
  404.                  * PostScript Language Reference Manual, 2nd Edition,
  405.                  * we must bypass the C, M, and Y transfer functions in this case.
  406.                  */
  407.     frac mgray = gx_map_color_frac(pis, gray, effective_transfer.colored.gray);
  408.  
  409.     if (gx_render_gray(mgray, pdc, pis, dev, select) == 1)
  410.     gx_color_load_select(pdc, pis, dev, select);
  411. }
  412.  
  413. private void
  414. cmap_gray_to_cmyk_direct(frac gray, gx_device_color * pdc,
  415.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  416. {                /*
  417.                  * Per the last paragraph of section 6.3 (p. 309) of the
  418.                  * PostScript Language Reference Manual, 2nd Edition,
  419.                  * we must bypass the C, M, and Y transfer functions in this case.
  420.                  */
  421.     frac mgray = gx_map_color_frac(pis, gray, effective_transfer.colored.gray);
  422.     frac mblack = frac_1 - mgray;
  423.     gx_color_index color =
  424.     gx_map_cmyk_color(dev,
  425.               frac2cv(frac_0), frac2cv(frac_0),
  426.               frac2cv(frac_0), frac2cv(mblack));
  427.  
  428.     if (color != gx_no_color_index) {
  429.     color_set_pure(pdc, color);
  430.     return;
  431.     }
  432.     if (gx_render_gray(mgray, pdc, pis, dev, select) == 1)
  433.     gx_color_load_select(pdc, pis, dev, select);
  434. }
  435.  
  436. /* ------ Render RGB color. ------ */
  437.  
  438. /*
  439.  * This code should test r == g and g == b and then use the gray
  440.  * rendering procedures.  The Adobe documentation allows this:
  441.  * conversion between color spaces occurs before the transfer function
  442.  * and halftoning.  However, output from FrameMaker (mis)uses the
  443.  * transfer function to provide the equivalent of indexed color;
  444.  * it requires the color components to be passed through unchanged.
  445.  * For this reason, we have to make the check after the transfer
  446.  * function rather than before.
  447.  *
  448.  * Since this procedure is used so heavily, we duplicate most of its code
  449.  * rather than making a text for color_info.max_color >= 31.
  450.  */
  451.  
  452. private void
  453. cmap_rgb_halftoned(frac r, frac g, frac b, gx_device_color * pdc,
  454.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  455. {
  456.     frac mred = gx_map_color_frac(pis, r, effective_transfer.colored.red);
  457.     frac mgreen = gx_map_color_frac(pis, g, effective_transfer.colored.green);
  458.     frac mblue = gx_map_color_frac(pis, b, effective_transfer.colored.blue);
  459.  
  460.     if ((mred == mgreen && mred == mblue ?    /* gray shade */
  461.      gx_render_gray(mred, pdc, pis, dev, select) :
  462.      gx_render_rgb(mred, mgreen, mblue, pdc, pis, dev, select)) == 1)
  463.     gx_color_load_select(pdc, pis, dev, select);
  464. }
  465.  
  466. private void
  467. cmap_rgb_direct(frac r, frac g, frac b, gx_device_color * pdc,
  468.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  469. {
  470.     frac mred = gx_map_color_frac(pis, r, effective_transfer.colored.red);
  471.     frac mgreen = gx_map_color_frac(pis, g, effective_transfer.colored.green);
  472.     frac mblue = gx_map_color_frac(pis, b, effective_transfer.colored.blue);
  473.     gx_color_index color =
  474.     (pis->alpha == gx_max_color_value ?
  475.      gx_map_rgb_color(dev, frac2cv(mred), frac2cv(mgreen),
  476.               frac2cv(mblue)) :
  477.      gx_map_rgb_alpha_color(dev, frac2cv(mred), frac2cv(mgreen),
  478.                 frac2cv(mblue), pis->alpha));
  479.  
  480.     if (color != gx_no_color_index) {
  481.     color_set_pure(pdc, color);
  482.     return;
  483.     }
  484.     if ((mred == mgreen && mred == mblue ?    /* gray shade */
  485.      gx_render_gray(mred, pdc, pis, dev, select) :
  486.      gx_render_rgb(mred, mgreen, mblue, pdc, pis, dev, select)) == 1)
  487.     gx_color_load_select(pdc, pis, dev, select);
  488. }
  489.  
  490. private void
  491. cmap_rgb_to_gray_halftoned(frac r, frac g, frac b, gx_device_color * pdc,
  492.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  493. {
  494.     cmap_gray_halftoned(color_rgb_to_gray(r, g, b, pis), pdc, pis, dev, select);
  495. }
  496.  
  497. private void
  498. cmap_rgb_to_gray_direct(frac r, frac g, frac b, gx_device_color * pdc,
  499.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  500. {
  501.     cmap_gray_direct(color_rgb_to_gray(r, g, b, pis), pdc, pis, dev, select);
  502. }
  503.  
  504. private void
  505. cmap_rgb_to_cmyk(frac r, frac g, frac b, gx_device_color * pdc,
  506.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  507. {
  508.     frac cmyk[4];
  509.  
  510.     color_rgb_to_cmyk(r, g, b, pis, cmyk);
  511.     (*pis->cmap_procs->map_cmyk) (cmyk[0], cmyk[1], cmyk[2], cmyk[3], pdc, pis, dev, select);
  512. }
  513.  
  514. /* ------ Render CMYK color. ------ */
  515.  
  516. private void
  517. cmap_cmyk_to_gray(frac c, frac m, frac y, frac k, gx_device_color * pdc,
  518.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  519. {
  520.     (*pis->cmap_procs->map_gray) (color_cmyk_to_gray(c, m, y, k, pis), pdc, pis, dev, select);
  521. }
  522.  
  523. private void
  524. cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
  525.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  526. {
  527.     frac mcyan = frac_1 - gx_map_color_frac(pis, frac_1 - c, effective_transfer.colored.red);
  528.     frac mmagenta = frac_1 - gx_map_color_frac(pis, frac_1 - m, effective_transfer.colored.green);
  529.     frac myellow = frac_1 - gx_map_color_frac(pis, frac_1 - y, effective_transfer.colored.blue);
  530.     frac mblack = frac_1 - gx_map_color_frac(pis, frac_1 - k, effective_transfer.colored.gray);
  531.  
  532.     /* We make a test for direct vs. halftoned, rather than */
  533.     /* duplicating most of the code of this procedure. */
  534.     if (!gx_color_device_must_halftone(dev)) {
  535.     gx_color_index color =
  536.     gx_map_cmyk_color(dev,
  537.               frac2cv(mcyan), frac2cv(mmagenta),
  538.               frac2cv(myellow), frac2cv(mblack));
  539.  
  540.     if (color != gx_no_color_index) {
  541.         color_set_pure(pdc, color);
  542.         return;
  543.     }
  544.     }
  545.     /* Don't convert colors with C = M = Y to gray shades: */
  546.     /* on a CMYK device, this may produce quite different output. */
  547.     if (gx_render_cmyk(mcyan, mmagenta, myellow, mblack, pdc, pis, dev, select) == 1)
  548.     gx_color_load_select(pdc, pis, dev, select);
  549. }
  550.  
  551. private void
  552. cmap_cmyk_to_rgb(frac c, frac m, frac y, frac k, gx_device_color * pdc,
  553.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  554. {
  555.     frac rgb[3];
  556.  
  557.     color_cmyk_to_rgb(c, m, y, k, pis, rgb);
  558.     (*pis->cmap_procs->map_rgb) (rgb[0], rgb[1], rgb[2], pdc, pis, dev, select);
  559. }
  560.  
  561. /* ------ Render RGB+alpha color. ------ */
  562.  
  563. #ifdef PREMULTIPLY_TOWARDS_WHITE
  564. #  define alpha_bias_value frac_1 - alpha
  565. #  define alpha_bias(v) ((v) + alpha_bias_value
  566. #else
  567. #  define alpha_bias(v) (v)
  568. #endif
  569.  
  570. private void
  571. cmap_rgb_alpha2gray_halftoned(frac r, frac g, frac b, frac alpha,
  572.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  573.                   gs_color_select_t select)
  574. {
  575.     frac gray = color_rgb_to_gray(r, g, b, pis);
  576.  
  577.     if (alpha != frac_1)    /* premultiply */
  578.     gray = alpha_bias((frac) ((long)gray * alpha / frac_1));
  579.     if (gx_render_gray_alpha(gx_map_color_frac(pis, gray, effective_transfer.colored.gray), frac2cv(alpha), pdc, pis, dev, select) == 1)
  580.     gx_color_load_select(pdc, pis, dev, select);
  581. }
  582.  
  583. private void
  584. cmap_rgb_alpha2gray_direct(frac r, frac g, frac b, frac alpha,
  585.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  586.                gs_color_select_t select)
  587. {
  588.     frac gray = color_rgb_to_gray(r, g, b, pis);
  589.  
  590.     if (alpha != frac_1)    /* premultiply */
  591.     gray = alpha_bias((frac) ((long)gray * alpha / frac_1));
  592.     {
  593.     frac mgray =
  594.     gx_map_color_frac(pis, gray, effective_transfer.colored.gray);
  595.     gx_color_value cv_gray = frac2cv(mgray);
  596.     gx_color_index color =
  597.     (alpha == frac_1 ?
  598.      gx_map_rgb_color(dev, cv_gray, cv_gray, cv_gray) :
  599.      gx_map_rgb_alpha_color(dev, cv_gray, cv_gray, cv_gray, frac2cv(alpha)));
  600.  
  601.     if (color == gx_no_color_index) {
  602.         if (gx_render_gray_alpha(mgray, frac2cv(alpha), pdc, pis, dev, select) == 1)
  603.         gx_color_load_select(pdc, pis, dev, select);
  604.         return;
  605.     }
  606.     color_set_pure(pdc, color);
  607.     }
  608. }
  609.  
  610. private void
  611. cmap_rgb_alpha_halftoned(frac r, frac g, frac b, frac alpha,
  612.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  613.              gs_color_select_t select)
  614. {
  615.     frac red = r, green = g, blue = b;
  616.  
  617.     if (alpha != frac_1) {    /* premultiply */
  618.     red = alpha_bias((frac) ((long)red * alpha / frac_1));
  619.     green = alpha_bias((frac) ((long)green * alpha / frac_1));
  620.     blue = alpha_bias((frac) ((long)blue * alpha / frac_1));
  621.     } {
  622.     frac mred =
  623.     gx_map_color_frac(pis, red, effective_transfer.colored.red);
  624.     frac mgreen =
  625.     gx_map_color_frac(pis, green, effective_transfer.colored.green);
  626.     frac mblue =
  627.     gx_map_color_frac(pis, blue, effective_transfer.colored.blue);
  628.     gx_color_value cv_alpha = frac2cv(alpha);
  629.  
  630.     if ((mred == mgreen && mred == mblue ?    /* gray shade */
  631.          gx_render_gray_alpha(mred, cv_alpha, pdc, pis, dev, select) :
  632.          gx_render_rgb_alpha(mred, mgreen, mblue, cv_alpha, pdc, pis, dev, select)) == 1)
  633.         gx_color_load_select(pdc, pis, dev, select);
  634.     }
  635. }
  636.  
  637. private void
  638. cmap_rgb_alpha_direct(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
  639.      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
  640. {
  641.     frac red = r, green = g, blue = b;
  642.  
  643.     if (alpha != frac_1) {    /* premultiply */
  644.     red = alpha_bias((frac) ((long)red * alpha / frac_1));
  645.     green = alpha_bias((frac) ((long)green * alpha / frac_1));
  646.     blue = alpha_bias((frac) ((long)blue * alpha / frac_1));
  647.     } {
  648.     frac mred =
  649.     gx_map_color_frac(pis, red, effective_transfer.colored.red);
  650.     frac mgreen =
  651.     gx_map_color_frac(pis, green, effective_transfer.colored.green);
  652.     frac mblue =
  653.     gx_map_color_frac(pis, blue, effective_transfer.colored.blue);
  654.     gx_color_value cv_alpha = frac2cv(alpha);
  655.     gx_color_index color =
  656.     (cv_alpha == gx_max_color_value ?
  657.      gx_map_rgb_color(dev, frac2cv(mred), frac2cv(mgreen),
  658.               frac2cv(mblue)) :
  659.      gx_map_rgb_alpha_color(dev, frac2cv(mred), frac2cv(mgreen),
  660.                 frac2cv(mblue), cv_alpha));
  661.  
  662.     if (color != gx_no_color_index) {
  663.         color_set_pure(pdc, color);
  664.         return;
  665.     }
  666.     if ((mred == mgreen && mred == mblue ?    /* gray shade */
  667.          gx_render_gray_alpha(mred, cv_alpha, pdc, pis, dev, select) :
  668.          gx_render_rgb_alpha(mred, mgreen, mblue, cv_alpha, pdc, pis, dev, select)) == 1)
  669.         gx_color_load_select(pdc, pis, dev, select);
  670.     }
  671. }
  672.  
  673. /* Currently CMYK devices can't handle alpha. */
  674. /* Just multiply the values towards white. */
  675. private void
  676. cmap_rgb_alpha_to_cmyk(frac r, frac g, frac b, frac alpha,
  677.     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
  678.                gs_color_select_t select)
  679. {
  680. #ifdef PREMULTIPLY_TOWARDS_WHITE
  681. #  undef alpha_bias_value
  682.     frac alpha_bias_value = frac_1 - alpha;
  683.  
  684. #endif
  685.  
  686.     cmap_rgb_to_cmyk(alpha_bias((frac) ((long)r * alpha / frac_1)),
  687.              alpha_bias((frac) ((long)g * alpha / frac_1)),
  688.              alpha_bias((frac) ((long)b * alpha / frac_1)),
  689.              pdc, pis, dev, select);
  690. }
  691.  
  692. #undef alpha_bias
  693. #undef alpha_bias_value
  694.  
  695. /* ------ Transfer function mapping ------ */
  696.  
  697. /* Define an identity transfer function. */
  698. float
  699. gs_identity_transfer(floatp value, const gx_transfer_map * pmap)
  700. {
  701.     return value;
  702. }
  703.  
  704. /* Define the generic transfer function for the library layer. */
  705. /* This just returns what's already in the map. */
  706. float
  707. gs_mapped_transfer(floatp value, const gx_transfer_map * pmap)
  708. {
  709.     return gx_map_color_float(pmap, value);
  710. }
  711.  
  712. /* Set a transfer map to the identity map. */
  713. void
  714. gx_set_identity_transfer(gx_transfer_map *pmap)
  715. {
  716.     int i;
  717.  
  718.     pmap->proc = gs_identity_transfer;
  719.     /* We still have to fill in the cached values. */
  720.     for (i = 0; i < transfer_map_size; ++i)
  721.     pmap->values[i] = bits2frac(i, log2_transfer_map_size);
  722. }
  723.  
  724. #if FRAC_MAP_INTERPOLATE    /* NOTA BENE */
  725.  
  726. /* Map a color fraction through a transfer map. */
  727. /* We only use this if we are interpolating. */
  728. frac
  729. gx_color_frac_map(frac cv, const frac * values)
  730. {
  731. #define cp_frac_bits (frac_bits - log2_transfer_map_size)
  732.     int cmi = frac2bits_floor(cv, log2_transfer_map_size);
  733.     frac mv = values[cmi];
  734.     int rem, mdv;
  735.  
  736.     /* Interpolate between two adjacent values if needed. */
  737.     rem = cv - bits2frac(cmi, log2_transfer_map_size);
  738.     if (rem == 0)
  739.     return mv;
  740.     mdv = values[cmi + 1] - mv;
  741. #if arch_ints_are_short
  742.     /* Only use long multiplication if necessary. */
  743.     if (mdv < -1 << (16 - cp_frac_bits) ||
  744.     mdv > 1 << (16 - cp_frac_bits)
  745.     )
  746.     return mv + (uint) (((ulong) rem * mdv) >> cp_frac_bits);
  747. #endif
  748.     return mv + ((rem * mdv) >> cp_frac_bits);
  749. #undef cp_frac_bits
  750. }
  751.  
  752. #endif /* FRAC_MAP_INTERPOLATE */
  753.  
  754. /* ------ Default device color mapping ------ */
  755.  
  756. /* RGB mapping for black-and-white devices */
  757.  
  758. /* White-on-black */
  759. gx_color_index
  760. gx_default_w_b_map_rgb_color(gx_device * dev,
  761.                gx_color_value r, gx_color_value g, gx_color_value b)
  762. {                /* Map values >= 1/2 to 1, < 1/2 to 0. */
  763.     return ((r | g | b) > gx_max_color_value / 2 ?
  764.         (gx_color_index) 1 : (gx_color_index) 0);
  765. }
  766. int
  767. gx_default_w_b_map_color_rgb(gx_device * dev, gx_color_index color,
  768.                  gx_color_value prgb[3])
  769. {                /* Map 1 to max_value, 0 to 0. */
  770.     prgb[0] = prgb[1] = prgb[2] = -(gx_color_value) color;
  771.     return 0;
  772. }
  773. /* Black-on-white */
  774. gx_color_index
  775. gx_default_b_w_map_rgb_color(gx_device * dev,
  776.                gx_color_value r, gx_color_value g, gx_color_value b)
  777. {                /* Map values >= 1/2 to 0, < 1/2 to 1. */
  778.     return ((r | g | b) > gx_max_color_value / 2 ?
  779.         (gx_color_index) 0 : (gx_color_index) 1);
  780. }
  781. int
  782. gx_default_b_w_map_color_rgb(gx_device * dev, gx_color_index color,
  783.                  gx_color_value prgb[3])
  784. {                /* Map 0 to max_value, 1 to 0. */
  785.     prgb[0] = prgb[1] = prgb[2] = -((gx_color_value) color ^ 1);
  786.     return 0;
  787. }
  788.  
  789. /* RGB mapping for gray-scale devices */
  790.  
  791. gx_color_index
  792. gx_default_gray_map_rgb_color(gx_device * dev,
  793.                gx_color_value r, gx_color_value g, gx_color_value b)
  794. {                /* We round the value rather than truncating it. */
  795.     gx_color_value gray =
  796.     (((r * (ulong) lum_red_weight) +
  797.       (g * (ulong) lum_green_weight) +
  798.       (b * (ulong) lum_blue_weight) +
  799.       (lum_all_weights / 2)) / lum_all_weights
  800.      * dev->color_info.max_gray +
  801.      (gx_max_color_value / 2)) / gx_max_color_value;
  802.  
  803.     return gray;
  804. }
  805.  
  806. int
  807. gx_default_gray_map_color_rgb(gx_device * dev, gx_color_index color,
  808.                   gx_color_value prgb[3])
  809. {
  810.     gx_color_value gray =
  811.     color * gx_max_color_value / dev->color_info.max_gray;
  812.  
  813.     prgb[0] = gray;
  814.     prgb[1] = gray;
  815.     prgb[2] = gray;
  816.     return 0;
  817. }
  818.  
  819. /* RGB mapping for 24-bit true (RGB) color devices */
  820.  
  821. gx_color_index
  822. gx_default_rgb_map_rgb_color(gx_device * dev,
  823.                gx_color_value r, gx_color_value g, gx_color_value b)
  824. {
  825.     if (dev->color_info.depth == 24)
  826.     return gx_color_value_to_byte(b) +
  827.         ((uint) gx_color_value_to_byte(g) << 8) +
  828.         ((ulong) gx_color_value_to_byte(r) << 16);
  829.     else {
  830.     int bpc = dev->color_info.depth / 3;
  831.     int drop = sizeof(gx_color_value) * 8 - bpc;
  832.  
  833.     return ((((r >> drop) << bpc) + (g >> drop)) << bpc) + (b >> drop);
  834.     }
  835. }
  836.  
  837. /* Map a color index to a r-g-b color. */
  838. int
  839. gx_default_rgb_map_color_rgb(gx_device * dev, gx_color_index color,
  840.                  gx_color_value prgb[3])
  841. {
  842.     if (dev->color_info.depth == 24) {
  843.     prgb[0] = gx_color_value_from_byte(color >> 16);
  844.     prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
  845.     prgb[2] = gx_color_value_from_byte(color & 0xff);
  846.     } else {
  847.     uint bits_per_color = dev->color_info.depth / 3;
  848.     uint color_mask = (1 << bits_per_color) - 1;
  849.  
  850.     prgb[0] = ((color >> (bits_per_color * 2)) & color_mask) *
  851.         (ulong) gx_max_color_value / color_mask;
  852.     prgb[1] = ((color >> (bits_per_color)) & color_mask) *
  853.         (ulong) gx_max_color_value / color_mask;
  854.     prgb[2] = (color & color_mask) *
  855.         (ulong) gx_max_color_value / color_mask;
  856.     }
  857.     return 0;
  858. }
  859.  
  860. /* CMYK mapping for RGB devices (should never be called!) */
  861.  
  862. gx_color_index
  863. gx_default_map_cmyk_color(gx_device * dev,
  864.      gx_color_value c, gx_color_value m, gx_color_value y, gx_color_value k)
  865. {                /* Convert to RGB */
  866.     frac rgb[3];
  867.  
  868.     color_cmyk_to_rgb(cv2frac(c), cv2frac(m), cv2frac(y), cv2frac(k),
  869.               NULL, rgb);
  870.     return gx_map_rgb_color(dev, frac2cv(rgb[0]),
  871.                 frac2cv(rgb[1]), frac2cv(rgb[2]));
  872. }
  873.  
  874. /* Mapping for CMYK devices */
  875.  
  876. gx_color_index
  877. cmyk_1bit_map_cmyk_color(gx_device * dev,
  878.              gx_color_value c, gx_color_value m,
  879.              gx_color_value y, gx_color_value k)
  880. {
  881. #define CV_BIT(v) ((v) >> (gx_color_value_bits - 1))
  882.     return (gx_color_index)
  883.     (CV_BIT(k) + (CV_BIT(y) << 1) + (CV_BIT(m) << 2) + (CV_BIT(c) << 3));
  884. #undef CV_BIT
  885. }
  886.  
  887. int
  888. cmyk_1bit_map_color_rgb(gx_device * dev, gx_color_index color,
  889.             gx_color_value prgb[3])
  890. {
  891.     if (color & 1)
  892.     prgb[0] = prgb[1] = prgb[2] = 0;
  893.     else {
  894.     prgb[0] = (color & 8 ? 0 : gx_max_color_value);
  895.     prgb[1] = (color & 4 ? 0 : gx_max_color_value);
  896.     prgb[2] = (color & 2 ? 0 : gx_max_color_value);
  897.     }
  898.     return 0;
  899. }
  900.  
  901. gx_color_index
  902. cmyk_8bit_map_cmyk_color(gx_device * dev,
  903.              gx_color_value c, gx_color_value m,
  904.              gx_color_value y, gx_color_value k)
  905. {
  906.     gx_color_index color =
  907.     gx_color_value_to_byte(k) +
  908.     ((uint)gx_color_value_to_byte(y) << 8) +
  909.     ((uint)gx_color_value_to_byte(m) << 16) +
  910.     ((uint)gx_color_value_to_byte(c) << 24);
  911.  
  912.     return (color == gx_no_color_index ? color ^ 1 : color);
  913. }
  914.  
  915. int
  916. cmyk_8bit_map_color_rgb(gx_device * dev, gx_color_index color,
  917.             gx_color_value prgb[3])
  918. {
  919.     int
  920.     not_k = ~color & 0xff,
  921.     r = not_k - (color >> 24),
  922.     g = not_k - ((color >> 16) & 0xff),
  923.     b = not_k - ((color >> 8) & 0xff); 
  924.  
  925.     prgb[0] = (r < 0 ? 0 : gx_color_value_from_byte(r));
  926.     prgb[1] = (g < 0 ? 0 : gx_color_value_from_byte(g));
  927.     prgb[2] = (b < 0 ? 0 : gx_color_value_from_byte(b));
  928.     return 0;
  929. }
  930.  
  931. /* Default mapping between RGB+alpha and RGB. */
  932.  
  933. gx_color_index
  934. gx_default_map_rgb_alpha_color(gx_device * dev,
  935.  gx_color_value r, gx_color_value g, gx_color_value b, gx_color_value alpha)
  936. {                /* Colors have been premultiplied: we don't need to do it here. */
  937.     return gx_map_rgb_color(dev, r, g, b);
  938. }
  939.  
  940. int
  941. gx_default_map_color_rgb_alpha(gx_device * dev, gx_color_index color,
  942.                    gx_color_value prgba[4])
  943. {
  944.     prgba[3] = gx_max_color_value;    /* alpha = 1 */
  945.     return (*dev_proc(dev, map_color_rgb)) (dev, color, prgba);
  946. }
  947.